package com.jaj.services;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import com.jaj.common.JavaDocReader;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.ParamTag;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.Tag;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 将JavaDoc对象生成到excel
 *
 * @author j aj
 */
public class ExcelGenerateService {

    /**
     * 根据JavaDoc生成Excel
     * @param rootDoc JavaDoc对象
     */
    public static void generateExcel(RootDoc rootDoc,String projectName){
        String path="d:/接口说明.xlsx";
        File file = new File(path);
        try {
            XSSFWorkbook wb;
            if(file.exists()){
                //传入的文件
                InputStream fileInput = new FileInputStream(file);
                //创建工作簿---->XSSF代表10版的Excel(HSSF是03版的Excel)
                wb= new XSSFWorkbook(fileInput);
            }else {
                //创建工作簿---->XSSF代表10版的Excel(HSSF是03版的Excel)
                wb = new XSSFWorkbook();
            }
            //工作表
            int sheetIndex= wb.getSheetIndex(projectName+"接口列表");
            if(sheetIndex!=-1){
                wb.removeSheetAt(sheetIndex);
            }
            XSSFSheet sheet = wb.createSheet(projectName+"接口列表");
            //创建表头行
            createHeaderRow(sheet);
            //创建内容行
            addContent(rootDoc,sheet);
            //上面设置好了内容，我们当然是要输出到某个文件的，输出就需要有输出流
            FileOutputStream fos= null;
            fos = new FileOutputStream(path);
            //向指定文件写入内容
            wb.write(fos);
            fos.close();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加内容
     * @param rootDoc javaDoc
     */
    private static void addContent(RootDoc rootDoc,XSSFSheet sheet){
        int rowIndex=1;
        ClassDoc[] classes = rootDoc.classes();
        List<CellRangeAddress> cellRangeAddressList = new ArrayList<>();
        for (int i = 0; i < classes.length; ++i) {
            ClassDoc classDoc=classes[i];
            int mergeBeginRowIndex=rowIndex;
            for(MethodDoc methodDoc:classes[i].methods()){
                XSSFRow dataRow=sheet.createRow(rowIndex);
                XSSFCell serialNumberCell=dataRow.createCell(0);
                serialNumberCell.setCellValue(rowIndex);
                serialNumberCell.setCellStyle(createSerialNumberStyle(sheet));
                dataRow.createCell(1).setCellValue(classDoc.qualifiedName());
                dataRow.createCell(2).setCellValue(classDoc.commentText());
                dataRow.createCell(3).setCellValue(methodDoc.name());
                dataRow.createCell(4).setCellValue(methodDoc.commentText());
                StringBuffer sbParams = new StringBuffer();
                StringBuffer sbReturn = new StringBuffer();
                for (Tag tag : methodDoc.tags()) {
                    if(tag instanceof ParamTag){
                        sbParams.append(((ParamTag) tag).parameterName())
                                .append(((ParamTag) tag).parameterComment()).append("\n");
                    }
                    else if(tag.name().equals("@return")){
                        sbReturn.append(tag.text());
                    }
                }
                XSSFCellStyle paramCellStyle= createMethodCommentStyle(sheet);
                XSSFCell paramsCell= dataRow.createCell(5);
                paramsCell.setCellValue(sbParams.toString());
                //paramsCell.setCellStyle(paramCellStyle);

                dataRow.createCell(6).setCellValue(sbReturn.toString());
                dataRow.setHeightInPoints(20);
                rowIndex++;
            }
            int mergeEndRowIndex=rowIndex-1;
            // 合并单元格
            CellRangeAddress firstCellRangeAddress = new CellRangeAddress(mergeBeginRowIndex,mergeEndRowIndex,1,1);
            cellRangeAddressList.add(firstCellRangeAddress);
            CellRangeAddress secondCellRangeAddress = new CellRangeAddress(mergeBeginRowIndex,mergeEndRowIndex,2,2);
            cellRangeAddressList.add(secondCellRangeAddress);
        }
        // 合并单元格
        for (CellRangeAddress cellRangeAddress : cellRangeAddressList) {
            sheet.addMergedRegion(cellRangeAddress);
        }
    }

    /**
     * 创建表头行
     * @param sheet excel的Sheet页
     */
    private static void createHeaderRow(XSSFSheet sheet){
        //标头行，代表第一行
        XSSFRow header=sheet.createRow(0);
        //常见样式
        XSSFCellStyle headerStylee=createHeaderStyle(sheet);
        //创建单元格，0代表第一行第一列
        XSSFCell cell0=header.createCell(0);
        cell0.setCellValue("序号");
        cell0.setCellStyle(headerStylee);

        XSSFCell cell1= header.createCell(1);
        cell1.setCellValue("接口包的全路径");
        cell1.setCellStyle(headerStylee);

        XSSFCell cell2= header.createCell(2);
        cell2.setCellValue("接口描述");
        cell2.setCellStyle(headerStylee);

        XSSFCell cell3= header.createCell(3);
        cell3.setCellValue("方法");
        cell3.setCellStyle(headerStylee);

        XSSFCell cell4= header.createCell(4);
        cell4.setCellValue("方法描述");
        cell4.setCellStyle(headerStylee);

        XSSFCell cell5= header.createCell(5);
        cell5.setCellValue("入参");
        cell5.setCellStyle(headerStylee);

        XSSFCell cell6= header.createCell(6);
        cell6.setCellValue("返回值");
        cell6.setCellStyle(headerStylee);

        //设置列的宽度
        //getPhysicalNumberOfCells()代表这行有多少包含数据的列
        for(int i=0;i<header.getPhysicalNumberOfCells();i++){
            //POI设置列宽度时比较特殊，它的基本单位是1/255个字符大小，
            //因此我们要想让列能够盛的下20个字符的话，就需要用255*20
            //sheet.setColumnWidth(i, 255*30);
        }
        sheet.setColumnWidth(0, 255*8);//序号列的列宽
        sheet.setColumnWidth(1, 255*30);//接口包的全路径的列宽
        sheet.setColumnWidth(2, 255*30);//接口描述
        sheet.setColumnWidth(3, 255*30);//方法
        sheet.setColumnWidth(4, 255*30);//方法描述
        sheet.setColumnWidth(5, 255*30);//入参
        sheet.setColumnWidth(6, 255*100);//返回值
        //设置行高，行高的单位就是像素，因此30就是30像素的意思
        header.setHeightInPoints(20);

    }

    /**
     * 设置表头行的样式
     * @param sheet sheet页
     * @return XSSFCellStyle
     */
    private static  XSSFCellStyle createHeaderStyle(XSSFSheet sheet){
        //设置样式
        XSSFWorkbook workbook =sheet.getWorkbook();
        XSSFCellStyle cellStyle = workbook.createCellStyle(); // 单元格样式
        Font fontStyle = workbook.createFont(); // 字体样式
        fontStyle.setBold(true); // 加粗
        fontStyle.setFontName("黑体"); // 字体
        fontStyle.setFontHeightInPoints((short) 11); // 大小
        // 将字体样式添加到单元格样式中
        cellStyle.setFont(fontStyle);
        // 边框，居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//        cellStyle.setBorderBottom(BorderStyle.THIN);
//        cellStyle.setBorderLeft(BorderStyle.THIN);
//        cellStyle.setBorderRight(BorderStyle.THIN);
//        cellStyle.setBorderTop(BorderStyle.THIN);
        return cellStyle;
    }

    /**
     * 序号列的样式（居中）
     * @param sheet sheet页
     * @return XSSFCellStyle
     */
    private static  XSSFCellStyle createSerialNumberStyle(XSSFSheet sheet){
        //设置样式
        XSSFWorkbook workbook =sheet.getWorkbook();
        XSSFCellStyle cellStyle = workbook.createCellStyle(); // 单元格样式
        // 边框，居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return cellStyle;
    }


    /**
     * 方法参数注释列的样式（居中）
     * @param sheet sheet页
     * @return XSSFCellStyle
     */
    private static  XSSFCellStyle createMethodCommentStyle(XSSFSheet sheet){
        //设置样式
        XSSFWorkbook workbook =sheet.getWorkbook();
        XSSFCellStyle cellStyle = workbook.createCellStyle(); // 单元格样式
        // 边框，居中
        cellStyle.setWrapText(true);
        return cellStyle;
    }




    public static void main(String[] args) {
        //1意见反馈与评论
//        String path="D:\\sonlidev\\FeedBackSystem\\master\\witparking-feedback.interfaces\\src\\main\\java\\org\\witparking\\feedback\\interfaces";
//        String projectName="意见反馈与评论";
        //2长租项目
        String path="D:\\sonlidev\\WitparkingLeaseNew\\lease\\witparking-lease.interfaces\\src\\main\\java\\org\\witparking\\lease\\interfaces";
        String projectName="长租项目";
        //3共享泊位
//        String path="D:\\sonlidev\\ShareCarport\\ShareOrder\\witparking-share.interfaces\\src\\main\\java\\org\\witparking\\sharecarport\\interfaces";
//        String projectName="共享泊位";
        //4共享泊位-查询项目
//        String path="D:\\sonlidev\\ShareCarport\\ShareQuery\\witparking-sharequery.interfaces\\src\\main\\java\\org\\witparking\\sharecarport\\interfaces";
//        String projectName="共享泊位-查询项目";
        //5 CMS项目
//        String path = "D:\\sonlidev\\WisdomPayment\\sonlicms\\Sonli.Cms-Interfaces\\src\\main\\java\\sonli\\cms\\interfaces";
//        String projectName = "CMS项目";

        RootDoc root= JavaDocReader.read(path);
        generateExcel(root,projectName);
        //generateExcel(null);
    }
}
